package com.google.code.robot;

import java.awt.Point;
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;
import java.util.regex.*;

import org.dom4j.DocumentException;
import org.json.*;
import org.jsoup.Jsoup;
import org.jsoup.nodes.*;
import org.jsoup.select.*;

import com.google.code.constant.ALIGN;
import com.google.code.constant.DECISION;
import com.google.code.constant.ITEM_POS;
import com.google.code.constant.MISSION;
import com.google.code.constant.N;
import com.google.code.constant.STATUS;
import com.google.code.constant.STR;
import com.google.code.constant.T;
import com.google.code.constant.WARRIOR;
import com.google.code.constant.WEAL;
import com.google.code.constant.WUGUAN;
import com.google.code.datastructure.TreeSearch;
import com.google.code.io.OUT;
import com.google.code.util.*;
import com.google.code.web.*;

public class Robot extends Thread {
	public Player player;
	private HttpEngine eng;
	private final String bUrl = "http://s8.hero.9wee.com";
	private final int ConserveEP = 50;
	// private long lastUpdateTime = -1;
	// private long lastGoBackTownTime = -1;
	private long lastLazyCheckTime = -1;
	private long lazyCheckTS = 30 * T._1MinMS;
	private long lastGetGiftTime = -1;

	private long lastLoginTime = -1;
	private long lastMianChiTime = -1;

	private boolean isWarriorRun = false;
	private boolean isMianChiRewardGet = false;
	private boolean isBeautyRun = false;
	private boolean isWealRun = false;
	private boolean isSignIn = false;
	private boolean isWuGuanRun = false;
	private long refreshTime = -1;
	// private Calendar CAL8 = null;
	// private Calendar CAL13 = null;
	private String outputEncoding = null;

	{
		try {
			this.outputEncoding = HeroConf.getInstance().getOutputEncoding();
		} catch (DocumentException e) {
		}
		if (this.outputEncoding == null)
			this.outputEncoding = "UTF-8";
	}

	public Robot(String username, String password) throws Exception {
		this.player = new Player(username, password);
		this.initHttpEngine(username);
		this.login();
		this.init();
	}

	public Robot(Player player) {
		this.player = player;
		this.initHttpEngine(this.player.getUsername());
		this.login();
		this.init();
	}

	// init
	// ************************************************************
	public void initHttpEngine(String username) {
		// CookieManager cm = this.getCookie();
		CookieManager cm = new CookieManager();
		this.eng = new HttpEngine(cm);

		// if (cm == null) {
		// this.eng = new HttpEngine();
		// } else {
		// this.eng = new HttpEngine(cm);
		// }
	}

	private void init() {

		if (this.player.isLoggedIn() == false)
			return;
		else
			this.player.setLoginTime(T.TS());
	}

	// login
	// ************************************************************
	// private CookieManager getCookie() {
	// File f = new File(this.player.getUsername() + ".cm");
	// CookieManager cm = null;
	// try {
	// FileInputStream fis = new FileInputStream(f);
	// ObjectInputStream ois = new ObjectInputStream(fis);
	// cm = (CookieManager) ois.readObject();
	// ln(": using saved cookie");
	// } catch (Exception e) {
	// }
	// return cm;
	// }

	private void dumpCookie() {
		CookieManager cm = this.eng.getCookieManager();
		try {
			ObjectOutputStream out = new ObjectOutputStream(
					new FileOutputStream(this.player.getUsername() + ".cm"));
			out.writeObject(cm);
		} catch (Exception e) {
			ln(": save cookie failed.");
			e.printStackTrace();
		}
	}

	private boolean login() {
		DECISION d = this.isLogedIn(null);
		if (d == DECISION.TRUE) {
			ln(": local cookie valide");
			return true;
		}

		boolean b = false;

		try {
			b = _login();
		} catch (Exception e) {

		}

		this.lastLoginTime = T.TS();
		return b;
	}

	private boolean _login() throws Exception {
		this.eng.get(this.bUrl, null, null);

		KVPair[] ps = new KVPair[] {
				new KVPair("username", this.player.getUsername()),
				new KVPair("password", this.player.getPassword()),
				new KVPair("_REFERER", this.bUrl
						+ "/passport.php?act=login&referer=/") };

		this.eng.post("https://passport.9wee.com/login", null, ps);
		int code = this.eng.getResponseCode();

		if (code == 302) {
			String loc = this.eng.getHeaderField("location");
			redirect(loc);
		}

		this.isLogedIn(null);
		if (this.player.isLoggedIn()) {
			this.dumpCookie();
			ln(": Logged in");
		}
		return this.player.isLoggedIn();
	}

	private void redirect(String location) throws Exception {
		// System.out.println("redirect to: " + location);
		HttpURLConnection.setFollowRedirects(false);
		this.eng.get(location, null, null);
		int code = this.eng.getResponseCode();

		if (code == 302) {
			String loc = this.eng.getHeaderField("location");
			if (!loc.startsWith("http")) {
				URL url = new URL(location);
				loc = url.getProtocol() + "://" + url.getHost() + loc;
			}
			redirect(loc);
		}
	}

	// req wrapper
	// ************************************************************
	public String exec(String url) {
		return exec("GET", url, null, null);
	}

	public String exec(String url, KVPair[] headers, KVPair[] parmas) {
		return this.exec("POST", url, headers, parmas);
	}

	public String exec(String method, String url, KVPair[] headers,
			KVPair[] parmas) {
		if (method == null)
			method = "GET";
		String ret = null;
		int tryTimes = 5;

		while (tryTimes > 0) {
			try {
				if (method.equalsIgnoreCase("GET"))
					this.eng.get(url, headers, null);
				else
					this.eng.post(url, headers, parmas);
				ret = this.eng.getResponseHtml();
				break;
			} catch (Exception e) {
				ln(": exec error - " + e.toString());
			}
			tryTimes--;
		}

		return ret;
	}

	// dump wrapper
	// ************************************************************
	public void l(Object msg) {
		// String un = this.player.getNickname();
		// if (un == null)
		// un = this.player.getUsername();

		String un = this.player.getUsername();
		msg = "[" + T.TIME() + "] " + STRING.Align(un, 12, ALIGN.RIGHT, ' ')
				+ msg.toString();

		OUT.print(msg, this.outputEncoding);
	}

	public void ln(Object msg) {
		// String un = this.player.getNickname();
		// if (un == null)
		// un = this.player.getUsername();

		String un = this.player.getUsername();
		msg = "[" + T.TIME() + "] " + STRING.Align(un, 12, ALIGN.RIGHT, ' ')
				+ msg.toString();

		OUT.println(msg, this.outputEncoding);
	}

	// user information
	// ************************************************************
	public String getRoleInfo() {
		String u = this.bUrl + "/modules/role_info.php?mod=role_base&time="
				+ T.TS() + "&timeStamp=" + T.TS()
				+ "&callback_func_name=callback_load_modules";
		// http://s8.hero.9wee.com/modules/role_info.php?mod=role_base&time=1336217270793&timeStamp=1336217248893&callback_func_name=callback_load_modules
		return exec(u);
	}

	public int getLevel(String info) {
		if (info == null)
			info = this.getRoleInfo();

		if (!this.player.isLoggedIn())
			return -1;

		if (info == null)
			return -1;

		int iRet = -1;
		JSONObject obj;
		try {
			obj = new JSONObject(info);
			info = obj.get("role_base").toString();
		} catch (JSONException e1) {
			return -1;
		}

		if (info == null)
			return -1;
		Document doc = Jsoup.parse(info);
		Elements links = doc.select("table>tr:eq(0)");

		if (links.isEmpty())
			return -1;
		Element e = links.get(0);

		Pattern p = Pattern.compile("Lv\\.([1-9][0-9]{0,2})");
		Matcher m = p.matcher(e.text());

		if (m.find()) {
			iRet = Integer.parseInt(m.group(1));
		}

		return iRet;
	}

	private int getEnergePoin(String info) {

		if (info == null)
			info = this.getRoleInfo();
		if (info == null)
			return -1;

		int iRet = -1;
		JSONObject obj;
		try {
			obj = new JSONObject(info);
			info = obj.get("role_base").toString();
		} catch (JSONException e1) {

		}

		if (info == null)
			return -1;
		Document doc = Jsoup.parse(info);
		Elements links = doc.select("table>tr:eq(4)>td>div");

		if (links.isEmpty())
			return -1;
		Element e = links.get(0);

		Pattern p = Pattern.compile("([0-9]{1,3})[ ]*/[ ]*[234]00");
		Matcher m = p.matcher(e.text());

		if (m.find()) {
			iRet = Integer.parseInt(m.group(1));
		}

		return iRet;
	}

	private String getUsername(String info) {
		if (info == null)
			info = this.getRoleInfo();

		String sRet = null;
		JSONObject obj;
		try {
			obj = new JSONObject(info);
			info = obj.get("role_base").toString();
		} catch (JSONException e1) {

		}

		if (info == null)
			return null;
		Document doc = Jsoup.parse(info);
		Elements links = doc.select("div>div>span:eq(1)>a");

		if (links.isEmpty())
			return null;
		Element e = links.get(0);
		sRet = e.text();
		return sRet;
	}

	private STATUS getStatus(String info) {
		if (info == null)
			info = this.getRoleInfo();

		if (info == null)
			return null;

		JSONObject obj;
		try {
			obj = new JSONObject(info);
			info = obj.get("role_base").toString();
		} catch (JSONException e1) {

		}

		if (info == null)
			return null;
		Document doc = Jsoup.parse(info);
		Elements links = doc.select("table>tr:eq(5)");
		if (links.isEmpty())
			return null;
		Element e = links.get(0);

		STATUS[] statuses = STATUS.values();
		for (STATUS status : statuses) {
			if (e.text().indexOf(status.val) != -1)
				return status;
		}

		return null;
	}

	// duel
	// ************************************************************
	public String getArenaData() {
		String link = bUrl
				+ "/modules/duel.php?act=hall&timeStamp="
				+ T.TS()
				+ "&callback_func_name=callback_load_content&callback_obj_name=content";
		return exec(link);
	}

	private int getDuleTimes(String arena) {
		if (arena == null)
			arena = this.getArenaData();

		if (arena == null)
			return -1;

		Document doc = Jsoup.parse(arena);
		Elements links = doc
				.select("html>body>div>div:eq(1)>div:eq(1)>span:eq(0)");

		if (links == null || links.size() == 0)
			return -1;

		Element e = links.get(0);
		Pattern p = Pattern.compile("([0-9]+)[ ]*/[ ]*[0-9]+");
		Matcher m = p.matcher(e.text());

		if (m.find()) {
			return Integer.parseInt(m.group(1));
		}

		return -1;
	}

	public ArrayList<Integer> getCompetetierList(String arena) {
		ArrayList<Integer> al = new ArrayList<Integer>();

		if (arena == null)
			return null;

		Pattern p = Pattern.compile("fnDuelRoleFight\\([\\ ]([0-9]+),",
				Pattern.MULTILINE);
		Matcher m = p.matcher(arena);

		while (m.find()) {
			al.add(Integer.parseInt(m.group(1)));
		}

		return al;
	}

	public int getDuelOpponet(String arena) {
		if (arena == null)
			arena = this.getArenaData();
		if (arena == null)
			return -1;

		Document doc = Jsoup.parse(arena);
		Elements tds = doc.select("table>tr>td:containsOwn(Lv.)");

		Pattern p = Pattern.compile("view_role[ ]*\\([ ]*([0-9]+)",
				Pattern.MULTILINE | Pattern.DOTALL);
		// Pattern plvl = Pattern.compile("[0-9]+");
		Matcher m1 = null;
		int iRet = -1;
		// int maxLvl = -1;
		for (Element el : tds) {
			// m = plvl.matcher(el.ownText());
			// if (!m.find())
			// continue;
			// iRet = Integer.parseInt(m.group());

			// if (t >= this.player.getLvl())
			// continue;
			// if (maxLvl > t)
			// continue;
			// else
			// maxLvl = t;

			if (tds.last() == el)
				break;

			el = el.parent();
			String str = el.toString();
			m1 = p.matcher(str);
			if (m1.find())
				iRet = Integer.parseInt(m1.group(1));
		}

		return iRet;
	}

	public int getArenaRank(String arena) {
		if (arena == null)
			arena = this.getArenaData();
		if (arena == null)
			return -1;

		Document doc = Jsoup.parse(arena);
		Element body = doc.body();

		Elements els = body.select("div>span:containsOwn(No.)");
		if (els.size() > 0) {
			Pattern p = Pattern.compile("[0-9]+");
			Matcher m = p.matcher(els.get(0).ownText());
			if (m.find()) {
				return Integer.parseInt(m.group());
			}
		}

		return -1;
	}

	public String randomDuel() {
		String arena = getArenaData();
		int id = -1;
		if (this.player.getLvl() < 60) {
			id = this.getDuelOpponet(arena);
			// ln("Opponet Id: " + id);
		} else {
			ArrayList<Integer> al = this.getCompetetierList(arena);
			// id = al.get((int) N.RND(1, 1));
			id = al.get(al.size() - 1);
		}
		String fightData = "/modules/duel_fight.php?action=fight&rid=" + id
				+ "&timeStamp="
				+ (Calendar.getInstance().getTimeInMillis() + 1001 * 60 * 10)
				+ "&callback_func_name=callbackFnDuelRoleFight";

		return this.exec(bUrl + fightData);
	}

	// task
	// ************************************************************
	public String getTaskInfo() {
		String u = bUrl
				+ "/modules/task.php?timeStamp="
				+ T.TS()
				+ "&callback_func_name=callback_load_content&callback_obj_name=content";
		return exec(u);
	}

	private int getAutoTaskId(String task) {
		if (task == null)
			return -1;

		Document doc = Jsoup.parse(task);
		Elements trs = doc.select("table.data_grid>tr:has(td)");
		for (Element tr : trs) {
			if (tr.text().indexOf(MISSION.AUTO.val) == -1)
				continue;

			int hour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
			if (tr.text().indexOf(MISSION.TYPE_COMBAT.val) == -1
					&& (hour - 4 < this.player.getAcptTaskNum() || hour < 8))
				continue;

			Elements links = tr.select("a[onclick]");
			if (links.isEmpty())
				continue;

			String script = links.get(0).attr("onclick");
			Pattern p = Pattern.compile("[0-9]+");
			Matcher m = p.matcher(script);
			if (m.find()) {
				return Integer.parseInt(m.group());
			}

		}
		return -1;
	}

	private int getImmedCompleteTaskId(String task) {
		if (task == null)
			return -1;

		Document doc = Jsoup.parse(task);
		Elements trs = doc.select("table.data_grid>tr");
		for (Element tr : trs) {
			if (tr.text().indexOf(MISSION.IMMEDIATE.val) == -1)
				continue;

			Elements links = tr.select("a[onclick]");
			if (links.isEmpty())
				continue;

			String script = links.get(0).attr("onclick");
			Pattern p = Pattern.compile("[0-9]+");
			Matcher m = p.matcher(script);
			if (m.find()) {
				return Integer.parseInt(m.group());
			}
		}
		return -1;
	}

	private int getRewardTaskId(String task) {
		if (task == null)
			task = getTaskInfo();
		if (task == null)
			return -1;

		Document doc = Jsoup.parse(task);
		Elements trs = doc.select("table.data_grid>tr");
		for (Element tr : trs) {
			if (tr.text().indexOf(MISSION.GET_REWARD.val) == -1)
				continue;

			Elements links = tr.select("a[onclick]");
			if (links.isEmpty())
				continue;

			String script = links.get(0).attr("onclick");
			Pattern p = Pattern.compile("[0-9]+");
			Matcher m = p.matcher(script);
			if (m.find()) {
				return Integer.parseInt(m.group());
			}
		}
		return -1;
	}

	public int getAcceptedTaskNum(String task) {
		if (task == null)
			task = this.getTaskInfo();
		if (task == null)
			return -1;

		Pattern p = Pattern.compile("([1]?[0-9]|20)[ ]*/[ ]*20");
		Document doc = Jsoup.parse(task);
		Elements links = doc.select("span");
		for (Element el : links) {
			Matcher m = p.matcher(el.ownText());
			if (m.find())
				return Integer.parseInt(m.group(1));
		}

		return -1;
	}

	private String autoTask(int id) {
		String link = bUrl
				+ "/modules/role_mission.php?act=detail&op=auto_complete&function=day&id="
				+ id + "&timeStamp=" + T.TS()
				+ "&callback_func_name=mission_common_callback";

		return this.exec(link);
	}

	private String getRevardOfTask(int id) {
		String link = bUrl
				+ "/modules/role_mission.php?act=rewards&function=day&id=" + id
				+ "&timeStamp=" + T.TS()
				+ "&callback_func_name=mission_common_callback";

		return this.exec(link);
	}

	public DECISION hasFreeAutoComplete(String task) {
		if (task == null)
			task = this.getTaskInfo();
		if (task == null)
			return DECISION.UNKNOWN;

		if (task.indexOf(MISSION.FREE_IMMEDIATE.val) != -1)
			return DECISION.TRUE;
		else
			return DECISION.FALSE;
	}

	public String complete_auto_mission(String task) {
		if (task == null)
			task = this.getTaskInfo();
		if (task == null)
			return null;

		Pattern p = Pattern
				.compile("complete_auto_mission[ ]*\\([ ]*\\'([0-9a-zA-Z]+)\\',[ ]*([0-9]+),[ ]*1");
		Matcher m = p.matcher(task);
		if (m.find()) {
			String url = bUrl + "/modules/role_mission.php?act=detail"
					+ "&op=complete_auto_mission&function=" + m.group(1)
					+ "&id=" + m.group(2) + "&isfree=1" + ""
					+ "&mission_common_callback";
			return this.exec(url);
		} else
			return null;
	}

	public String free_refresh(String task) {
		String str = bUrl + "/modules/task.php?refresh=1&isfree=1";

		return this.exec(str);
	}

	// warrior
	// ************************************************************
	// http://s7.hero.9wee.com
	public String getWarriorData() {
		String u = bUrl
				+ "/modules/warrior.php?act=arena&timeStamp="
				+ T.TS()
				+ "&callback_func_name=callback_load_content&callback_obj_name=content";
		// act=arena&timeStamp=1336145018044&callback_func_name=callback_load_content&callback_obj_name=content
		return exec(u);
	}

	public String joinWarrior(String warrior) {
		if (warrior == null)
			warrior = this.getWarriorData();

		if (warrior == null)
			return null;

		if (warrior.indexOf(WARRIOR.JOIN.val) == -1)
			return null;
		Document doc = Jsoup.parse(warrior);
		Element body = doc.body();

		TreeSearch ts = new TreeSearch() {
			@Override
			public Element process(Element el) {
				if (el.ownText().contains(WARRIOR.JOIN.val))
					return el;
				return null;
			}
		};
		Element a = ts.DFS(body);
		if (a == null)
			return null;
		String onclick = a.attr("onclick");
		String part = onclick.split(",")[1];
		int ip = Integer.parseInt(part.trim().replace("'", ""));
		String link = bUrl + "/modules/warrior.php?act=arena&op=join&part="
				+ ip + "&timeStamp=" + T.TS()
				+ "&callback_func_name=warrior_common_callback";

		return this.exec(link);
	}

	public String getArenaAwardKey(String arenaData) {
		if (arenaData == null)
			arenaData = this.getArenaData();

		Pattern p = Pattern
				.compile("arena_get_prise[ ]*\\([ ]*\\'([0-9][0-9_]*)\\'");
		Matcher m = p.matcher(arenaData);

		if (m.find())
			return m.group(1);
		else
			return null;
	}

	public String getWarriorPrise(String warrior) {
		if (warrior == null)
			warrior = this.getWarriorData();

		if (warrior == null)
			return null;

		if (warrior.indexOf(WARRIOR.GET.val) == -1)
			return null;

		// Document doc = Jsoup.parse(warrior);
		// Element body = doc.body();
		//
		// TreeSearch ts = new TreeSearch() {
		// @Override
		// public Element process(Element el) {
		// if (el.tagName().equalsIgnoreCase("input")
		// && el.hasAttr("value")
		// && el.attr("value").equalsIgnoreCase(WARRIOR.GET.val))
		// // if (el.ownText().contains(WARRIOR.GET.val))
		// return el;
		// return null;
		// }
		// };

		// Element a = ts.DFS(body);
		// if (a == null)
		// return null;
		// String onclick = a.attr("onclick");
		// // arena_get_prise ( '5_1_1336060800'
		// Pattern ptn = Pattern
		// .compile("arena_get_prise[ ]*[']([0-9_]+)['][ ]*,[ ]*[']([0-9]+)[']");
		// Matcher m = ptn.matcher(onclick);
		//
		// String key = "";
		// String mode = "";
		// if (m.find()) {
		// key = m.group(1);
		// mode = m.group(2);
		// }

		String key = this.getArenaAwardKey(warrior);
		System.out.println(key);

		// String u =
		// "/modules/warrior.php?act=arena&op=get_prise&submit=1&arena_key=2_1_1338998400&team_mode=0&timeStamp=1339065713678&callback_func_name=arena_get_prise_callback";

		String link = bUrl
				+ "/modules/warrior.php?act=arena&op=get_prise&submit=1&arena_key="
				+ key + "&team_mode=" + 0 + "&timeStamp=" + T.TS()
				+ "&callback_func_name=arena_get_prise_callback";
		// "modules/warrior.php?act=arena&op=get_prise&submit=1&arena_key=5_1_1336060800&team_mode=0&timeStamp=1336143284952";
		KVPair[] pairs = new KVPair[] { new KVPair("callback_func_name",
				"arena_get_prise_callback") };

		return this.exec(link, null, pairs);
	}

	// hall
	// ************************************************************
	public String startTrain(int hour) {
		String url = bUrl + "/modules/warrior.php?act=hall&op=train&hours="
				+ hour;
		KVPair[] pairs = new KVPair[] { new KVPair("callback_func_name",
				"train_callback") };
		return this.exec(url, null, pairs);
	}

	// weal
	// ************************************************************
	public String getWealHallData() {
		String u = bUrl
				+ "/modules/day_weals.php?act=show&rand="
				+ T.TS()
				+ "&timeStamp="
				+ T.TS()
				+ "&callback_func_name=ajaxCallback&callback_obj_name=dlg_view_weals";
		return exec(u);
	}

	public String getWealActData() {
		String u = bUrl
				+ "/modules/day_weals_activity.php?act=show&rand="
				+ T.TS()
				+ "&timeStamp="
				+ T.TS()
				+ "&callback_func_name=ajaxCallback&callback_obj_name=dlg_view_weals";
		return exec(u);
	}

	public String getDaliySignInData() {
		String u = this.bUrl
				+ "/modules/day_weals.php?act=show&rand="
				+ T.TS()
				+ "&timeStamp="
				+ T.TS()
				+ "&callback_func_name=ajaxCallback&callback_obj_name=dlg_view_weals";

		return exec(u);
	}

	public boolean DailySignIn() throws JSONException {
		String url = this.bUrl + "/modules/day_weals.php?act=weal&rand="
				+ T.TS() + "&timeStamp=" + T.TS()
				+ "&callback_func_name=callbackFnStartWeals";

		String str = exec(url);
		System.out.println(str);
		JSONObject jobj = new JSONObject(str);
		if (jobj.has("success"))
			return true;
		else {
			if (jobj.has("result")
					&& jobj.getString("result").contains(
							"\u660e\u5929\u518d\u6765"))
				return true;
			else
				return false;
		}
	}

	public DECISION canGetWeal(String weal) {
		if (weal == null)
			weal = this.getWealHallData();

		if (weal == null)
			return DECISION.UNKNOWN;

		if (weal.indexOf(STR.START_WEAL.msg) != -1)
			return DECISION.TRUE;
		else
			return DECISION.FALSE;
	}

	public DECISION canGetWealAct(String wealAct) {
		if (wealAct == null)
			wealAct = this.getWealActData();
		if (wealAct == null)
			return DECISION.UNKNOWN;

		if (wealAct.indexOf(WEAL.GET.val) == -1
				&& wealAct.indexOf(WEAL.GOT.val) != -1)
			return DECISION.FALSE;

		int iTask = -1, iDuel = -1;
		Document doc = Jsoup.parse(wealAct);
		Elements sps = doc.select("table:eq(1)>tr>td>span");
		if (sps.size() < 2)
			return DECISION.UNKNOWN;
		else
			try {
				iTask = Integer.parseInt(sps.get(0).text());
				iDuel = Integer.parseInt(sps.get(1).text());
			} catch (Exception e) {
				return DECISION.UNKNOWN;
			}

		if (iTask > 23 && iDuel > 23)
			return DECISION.TRUE;
		else
			return DECISION.FALSE;
	}

	public String startWeal() {
		String url = bUrl + "/modules/day_weals.php?act=weal&rand=" + T.TS();

		KVPair[] pairs = new KVPair[] { new KVPair("callback_func_name",
				"callbackFnStartWeals") };

		return this.exec(url, null, pairs);
	}

	public String actWeal() {
		String url = bUrl
				+ "/modules/day_weals_activity.php?act=weal&id=1rand=" + T.TS();

		return this.exec(url);
	}

	// beauty
	// ************************************************************
	public String getBeautyData(int id) {
		String url = bUrl + "/modules/beauty.php?act=show&set_id=" + id
				+ "&rand=" + T.TS();
		return this.exec(url);
	}

	public DECISION hasSetBeautyButton(String beauty, int id) {
		if (beauty == null)
			beauty = this.getBeautyData(id);

		if (beauty == null)
			return DECISION.UNKNOWN;

		Document doc = Jsoup.parse(beauty);
		Elements sets = doc.select("input#beauty_set_effect_button");
		if (sets.size() > 0)
			return DECISION.TRUE;
		else
			return DECISION.FALSE;
	}

	public DECISION canSetBeauty(String beauty, int id) {
		if (beauty == null)
			beauty = this.getBeautyData(id);

		if (beauty == null)
			return DECISION.UNKNOWN;

		DECISION d = this.hasSetBeautyButton(beauty, id);
		if (d != DECISION.TRUE)
			return d;

		Pattern p = Pattern.compile("^var[ ]+?jscurrentset.*?get_state.*?$",
				Pattern.MULTILINE);
		Matcher m = p.matcher(beauty);

		if (m.find())
			return DECISION.TRUE;
		else
			return DECISION.FALSE;
	}

	public String setBeautyEffect(int id) {
		String u = bUrl + "/modules/beauty.php?act=set_effect&set_id=" + id
				+ "&rand=" + T.TS() + "&timeStamp=" + T.TS()
				+ "&callback_func_name=" + "getBeautySetEffectCallback";
		return this.exec(u);
	}

	// combat
	// ************************************************************
	public String getCombatData() {
		String url = bUrl + "/modules/upgrade_help.php?"
				+ "act=practice&callback_func_name=dlg_view_practice";
		return this.exec(url);
	}

	public int getCombatPos(String combat) {
		if (combat == null)
			combat = this.getCombatData();
		if (combat == null)
			return -1;

		Pattern p = Pattern.compile("fnMoveToScene\\([ ]*([0-9]+),[ ]*500");
		Matcher m = p.matcher(combat);
		if (m.find()) {
			return Integer.parseInt(m.group(1));
		}
		return -1;
	}

	public String TP2Scene(int sid) {
		String str = bUrl
				+ "/modules/scene_walk.php?action=scene_move&scene_id=" + sid
				+ "&pk_status=" + 0 + "&rand=" + T.TS() + "&city_scene_id="
				+ "&callback_func_name=callbackFnMoveToScene";

		return this.exec(str);
	}

	public int getMonsterId(String scene) {
		if (this.player.getLvl() == -1)
			return -1;

		if (scene == null)
			scene = this.getSceneDate();
		if (scene == null)
			return -1;

		Pattern p = Pattern
				.compile("\"monster_id\"[ ]*:[ ]*\"([0-9]+)\"[ ]*,[ ]*\"level_range\"[ ]*:[ ]*\"Lv\\.([0-9]+)[ ]*-[ ]*([0-9]+)\"");
		Matcher m = p.matcher(scene);
		int t = -1;
		while (m.find()) {
			int mid = Integer.parseInt(m.group(1));
			int llv = Integer.parseInt(m.group(2));
			// int ulv = Integer.parseInt(m.group(3));

			if (this.player.getLvl() == (llv - 3))
				return mid;

			if (t < mid && this.player.getLvl() > (llv - 3))
				t = mid;
		}

		return t;
	}

	public int getCombatTime() {
		int iRet = -1;
		String url = this.bUrl + "/modules/auto_combats.php?act=view&rand="
				+ T.TS() + "&callback_func_name=" + "dlg_view_monster";

		String str = this.exec(url);
		Document doc = Jsoup.parse(str);
		Element body = doc.body();
		Elements els = body.select("script");
		if (els.size() == 0)
			return -1;
		Pattern ptn = Pattern.compile("[0-9]+");
		Matcher m = ptn.matcher(els.last().toString());
		if (m.find()) {
			try {
				iRet = Integer.parseInt(m.group());
			} catch (NumberFormatException e) {
			}
		}

		return iRet;
	}

	public String autoCombat(int mid, int times) {
		try {
			this.sellAllItems();
		} catch (Exception e) {
		}

		String link = "/modules/auto_combats.php?act=start&timeStamp=" + T.TS();
		KVPair[] params = new KVPair[] { new KVPair("mid", "" + mid),
				new KVPair("select_frequency", "" + times),
				new KVPair("callback_func_name", "callbackFnStartAutoCombat") };
		return this.exec(bUrl + link, null, params);
	}

	public String cancelCombat() {
		String url = bUrl + "/modules/auto_combats.php?act=cancel"
				+ "&callback_func_name=callbackFnCancelAutoCombat";
		return this.exec(url);
	}

	// others
	// ************************************************************
	private DECISION isInTown(String scene) {
		if (scene == null)
			scene = this.getSceneDate();

		if (scene == null)
			return DECISION.UNKNOWN;

		if (scene.indexOf("city_home_bg") == -1)
			return DECISION.FALSE;
		else
			return DECISION.TRUE;
	}

	public String getSceneDate() {
		String link = bUrl
				+ "/modules/scene.php?timeStamp="
				+ T.TS()
				+ "&callback_func_name=callback_load_stage&callback_obj_name=stage";
		return exec(link);
	}

	public DECISION goBackTown() {
		DECISION inTown = this.isInTown(null);
		if (DECISION.TRUE == inTown) {
			this.player.setCurPos("0");
			return DECISION.TRUE;
		}
		STATUS s = this.player.getStatus();
		if (!(s == STATUS.WEAK || s == STATUS.NORMAL))
			return DECISION.FALSE;

		String link = bUrl + "/modules/scenes_role.php?sid=0&timeStamp="
				+ T.TS() + "&callback_func_name=switch_scene_callback";
		this.exec(link);

		return this.isInTown(null);
	}

	public String walkIn1stLevel(int id) {
		String link = this.bUrl
				+ "/modules/scene_walk.php?action=world_move&scene_id=" + id
				+ "&rand=" + T.TS() + "&timeStamp=" + T.TS()
				+ "&callback_func_name=callbackFnWorldTransport";

		return this.exec(link);
	}

	public String walkIn2ndLevel(int id) {
		String link = this.bUrl + "/modules/scene_walk.php?action=walk&sid="
				+ id + "&g_time=" + T.TS() / 1000 + "&timeStamp=" + T.TS()
				+ "&callback_func_name=callbackfnScene";

		return this.exec(link);
	}

	public String walkIn3rdLevel(int id) {
		String link = this.bUrl
				+ "/modules/scene_walk.php?action=enterThirdScene&sid=" + id
				+ "&pk_status=0&hide_tips=0&isfree=0&g_time=" + T.TS() / 1000
				+ "&timeStamp=" + T.TS()
				+ "&callback_func_name=callbackfnEnterThirdScene";

		return this.exec(link);
	}

	public void sceneWalk(String path) {
		if (path == null || path.trim() == "")
			return;

		String[] pid = new String[] { "-1", "-1", "-1" };
		String[] t = path.split(",");
		for (int i = 0; i < 3 && i < t.length; i++)
			pid[i] = t[i].trim();

		String[] s = new String[] {
				"/modules/scene_walk.php?action=world_move&scene_id=" + pid[0]
						+ "&rand=" + T.TS() + "&timeStamp=" + T.TS()
						+ "&callback_func_name=callbackFnWorldTransport",
				"/modules/scene_walk.php?action=walk&sid=" + pid[1]
						+ "&g_time=" + T.TS() / 1000 + "&timeStamp=" + T.TS()
						+ "&callback_func_name=callbackfnScene",
				"/modules/scene_walk.php?action=enterThirdScene&sid=" + pid[2]
						+ "&pk_status=0&hide_tips=0&isfree=0&g_time=" + T.TS()
						/ 1000 + "&timeStamp=" + T.TS()
						+ "&callback_func_name=callbackfnEnterThirdScene" };

		for (int i = 0; i < 3 && i < t.length; i++) {
			if (pid[i] == "" || "-1".equals(pid[i])) {
				continue;
			}

			String rst = this.exec(bUrl + s[i]);
			if (rst.indexOf("error") == -1) {
				if ("0".equals(this.player.getCurPos())) {
					this.player.setCurPos("" + pid[i]);
				} else {
					this.player.setCurPos(this.player.getCurPos() + ","
							+ pid[i]);
				}
				ln(": go to level " + i + " scene of " + pid[i] + " succeed");
			} else {
				ln(": go to level " + i + " scene of " + pid[i] + " failed");
				break;
			}
		}
	}

	public String go2MianChi() {
		String url = bUrl + "/modules/scene_walk.php?action=world_move"
				+ "&scene_id=164&rand=" + T.TS()
				+ "&callback_func_name=callbackFnWorldTransport";

		return this.exec(url);
	}

	private DECISION isLogedIn(String html) {
		if (html == null)
			html = this.getRoleInfo();
		if (html == null)
			return DECISION.UNKNOWN;

		// if (html.indexOf(STR.NOT_LOGIN.getVal()) != -1) {
		if (html.indexOf("error") != -1 || html.isEmpty()) {
			this.player.setLoggedIn(false);
			// this.login();
			return DECISION.FALSE;
		} else {
			this.player.setLoggedIn(true);
			return DECISION.TRUE;
		}
	}

	private void SLEEP(long ms) {
		try {
			Thread.sleep(ms);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	// Wushu Center
	// ************************************************************
	public String getWuGuanData() {
		return this
				.exec(bUrl
						+ "/modules/team_foster.php?act=mission&callback_func_name=team_fostor_mission");

	}

	public DECISION can_get_team_mission(String tjt) {
		if (tjt == null)
			tjt = this.getWarriorData();
		if (tjt == null)
			return DECISION.UNKNOWN;

		Document doc = Jsoup.parse(tjt);
		Elements spans = doc.select("td>span");
		Pattern p = Pattern.compile("([0-9]+)[ ]*/[ ]*([0-9]+)");
		Matcher m = null;
		String s = null;
		for (Element span : spans) {
			s = span.toString();
			m = p.matcher(s);
			if (m.find()) {
				return Integer.parseInt(m.group(1)) == Integer.parseInt(m
						.group(2)) ? DECISION.FALSE : DECISION.TRUE;
			}
		}
		return DECISION.UNKNOWN;
	}

	public void auto_team_mission(String tjt) {
		if (tjt == null)
			tjt = this.getWarriorData();
		if (tjt == null)
			return;
		Document doc = Jsoup.parse(tjt);
		Elements links = doc.select("table.data_grid>tbody>tr:has(td)");

		for (Element tr : links) {
			if (tr.children().size() != 3)
				continue;

			String type = tr.child(0).text();
			if (!(WUGUAN.DUEL.val.equals(type)
					|| WUGUAN.GET_WEAL.val.equals(type)
					|| WUGUAN.HELP_MISSION.val.equals(type) || WUGUAN.BROKE_LIMIT.val
					.equals(type))) {
				continue;
			}

			String onclick = tr.child(2).child(0).attr("onclick");
			Pattern p = Pattern.compile("[0-9]+");
			Matcher m = p.matcher(onclick);
			if (m.find()) {
				String id = m.group();
				this.exec(bUrl
						+ "/modules/team_foster.php?act=mission&action=accept&mission_id="
						+ id + "&callback_func_name=refreshMissoin");

				this.exec(bUrl
						+ "/modules/team_foster.php?act=mission&action=finish&mission_id="
						+ id);

				this.exec(bUrl
						+ "/modules/team_foster.php?act=mission&action=remove&mission_id="
						+ id + "&callback_func_name=refreshMissoin");
			}
		}
	}

	// run
	// ************************************************************
	@Override
	public void run() {
		// while (this.player.isLoggedIn() == false) {
		// this.initHttpEngine(this.player.getUsername());
		// this.login();
		// this.init();
		// }

		while (true) {
			try {
				if (!this.player.isLoggedIn() || T.DUE_H(this.lastLoginTime, 8)) {
					this.initHttpEngine("");
					if (!this.login())
						continue;
				}

				this.runCheckStatus();
				this.runLazyCheck();

				if (this.player.getDuelTimes() > 14
						&& this.player.getAcptTaskNum() > 19
						&& this.player.getEp() <= this.ConserveEP
						&& this.isBeautyRun && this.isWealRun
						&& this.isWarriorRun && this.isMianChiRewardGet
						&& this.isWuGuanRun && this.isSignIn) {
					SLEEP(5 * T._1MinMS);
					return;
				}

				this.runDuel();

				STATUS s = this.player.getStatus();
				if (s == STATUS.NORMAL || s == STATUS.WEAK) {
					if (!this.isMianChiRewardGet)
						this.runMianChi();
				}

				if (s == STATUS.NORMAL || s == STATUS.WEAK || s == STATUS.TRAIN) {
					this.runTown();
				}

				if (s == STATUS.NORMAL || s == STATUS.WEAK)
					this.runCombat();
			} catch (Exception e) {
				e.printStackTrace();
			}

			SLEEP(5 * T._1MinMS);
		}
	} // run()

	private void runLazyCheck() {
		if (this.player.getAcptTaskNum() < 20
				&& this.player.getDuelTimes() < 15) {
			this.lastLazyCheckTime = T.TS();
			return;
		}

		long ts = Calendar.getInstance().getTimeInMillis()
				- this.lastLazyCheckTime;
		if (ts < this.lazyCheckTS)
			return;

		DECISION d = this.isInTown(null);
		int tn = -1;
		if (d == DECISION.TRUE) {
			tn = this.getAcceptedTaskNum(null);
			if (tn != -1)
				this.player.setAcptTaskNum(tn);
		}

		int dn = this.getDuleTimes(null);
		if (dn != -1)
			this.player.setDuelTimes(dn);

		if (tn != -1 && dn != -1)
			this.lastLazyCheckTime = T.TS();

		ln(": lazy check");
	}

	private void runCheckStatus() throws Exception {
		long ts8h = T.TS_OF_HOUR_OF_TODAY(8);
		if (this.refreshTime < ts8h && T.DUE(ts8h)) {
			this._login();

			this.isBeautyRun = false;
			this.isWarriorRun = false;
			this.isWuGuanRun = false;
			this.isMianChiRewardGet = false;
			this.isWealRun = false;
			this.refreshTime = T.TS() + 1;
			this.player.setAcptTaskNum(-1);
			this.player.setDuelTimes(-1);
			this.isSignIn = false;
		}

		if (T.DUE(this.lastGetGiftTime + T._1DayMS)
				&& this.player.getEp() <= this.ConserveEP) {

			ln("get gift");
			this.getGift(new String[] { "\u5168\u6C11\u798F\u5229\u793C\u5305",
					"\u52A0\u901F\u6210\u957F" });

			this.lastGetGiftTime = T.TS();
		}

		String info = this.getRoleInfo();

		if (this.player.getNickname() == null) {
			String nickname = this.getUsername(info);
			if (nickname != null)
				this.player.setNickname(nickname);
		}

		STATUS s = this.getStatus(info);
		if (s != null)
			this.player.setStatus(s);

		int lvl = this.getLevel(info);
		if (lvl != -1 && lvl >= this.player.getLvl())
			this.player.setLvl(lvl);

		int ep = this.getEnergePoin(info);
		if (ep != -1 && ep >= this.player.getEp())
			this.player.setEp(ep);

		// println(this.player);
	}

	public void runMianChi() {
		if (!T.DUE(this.lastMianChiTime + T._1DayMS))
			return;

		if (this.getArenaRank(null) > 128) {
			this.isMianChiRewardGet = true;
			this.lastMianChiTime = T.TS();
			return;
		}

		String str = this.go2MianChi();
		if (str.indexOf("164") == -1
				&& str.indexOf(STR.ALREADY_IN_SCENE.msg) == -1)
			return;

		this.getWarriorPrise(null);
		this.isMianChiRewardGet = true;
		this.lastMianChiTime = T.TS();
	}

	public void runTown() {
		DECISION d = this.goBackTown();
		if (d != DECISION.TRUE)
			return;

		STATUS s = this.player.getStatus();

		if (!this.isWealRun)
			this.runWeal();

		if (!this.isSignIn)
			this.runDailySignIn();

		if (!this.isBeautyRun && (s == STATUS.NORMAL || s == STATUS.WEAK))
			this.activeBeauty();

		if (!isWarriorRun)
			this.runWarrior();

		if (this.player.getAcptTaskNum() < 20)
			this.runTask();

		if (s != STATUS.TRAIN)
			this.runTrain();

		if (!this.isWuGuanRun)
			this.runWuGuan();
	}

	public void runWuGuan() {
		String tjt = this.getWuGuanData();
		DECISION d = this.can_get_team_mission(tjt);
		if (d == DECISION.FALSE)
			this.isWuGuanRun = true;

		if (d == DECISION.TRUE)
			this.auto_team_mission(tjt);

	}

	public void runDuel() {
		/**
		 * random duel if duel times not equal -1 and less than 15, besides 10
		 * minutes have passed since last duel.
		 */
		int dt = this.player.getDuelTimes();
		if (dt == -1)
			dt = this.getDuleTimes(null);

		if (dt < 0 || dt > 15)
			return;
		else
			this.player.setDuelTimes(dt);

		if ((T.TS() - this.player.getLastDuelTime()) < 1000 * 60 * 10)
			return;

		this.randomDuel();
		int times = this.getDuleTimes(null);
		if (this.player.getDuelTimes() < times) {
			this.player.setLastDuelTime(T.TS());
			this.player.setDuelTimes(times);
			ln(": duel (" + this.player.getDuelTimes() + ")succeed!");
		}
	}

	public void runCombat() throws DocumentException {
		int ep = this.player.getEp();
		if (ep <= this.ConserveEP)
			return;

		int sid = this.getCombatPos(null);
		this.TP2Scene(sid);
		int mid = this.getMonsterId(null);
		int runep = 24;
		if (ep - runep < this.ConserveEP)
			runep = ep - this.ConserveEP;
		if (mid != -1)
			this.autoCombat(mid, runep);
		else
			return;

		ep = this.getEnergePoin(null);
		if (ep != -1 && this.player.getEp() > ep) {
			this.player.setEp(ep);
			ln(": auto-combat " + ep);
		}
	}

	public void runTask() {
		if (this.player.getAcptTaskNum() > 19)
			return;

		String task = this.getTaskInfo();
		int num = this.getAcceptedTaskNum(task);
		if (num != -1)
			this.player.setAcptTaskNum(num);
		else
			return;

		int immedId = this.getImmedCompleteTaskId(task);
		int autoId = -1;
		if (immedId == -1) {
			autoId = this.getAutoTaskId(task);
			if (autoId != -1)
				this.autoTask(autoId);
		} else
			ln(": in-task " + immedId);

		int revardId = this.getRewardTaskId(task);
		if (revardId != -1) {
			this.getRevardOfTask(revardId);
		} else
			ln(": No reward to get.");

		task = this.getTaskInfo();
		int _num = this.getAcceptedTaskNum(task);
		int _revardId = this.getRewardTaskId(task);
		if (_num > num) {
			this.player.setAcptTaskNum(_num);
			ln(": auto-task " + autoId + "(" + _num + ")");
		}

		if (revardId != -1 && _revardId == -1)
			ln(": get-reward " + revardId);
	}

	public void runWarrior() {
		if (T.TS_OF_HOUR_OF_TODAY(13) > T.TS())
			return;

		String warrior = this.getWarriorData();
		boolean bJoin = warrior.indexOf(WARRIOR.JOIN.val) != -1;
		boolean bGet = warrior.indexOf(WARRIOR.GET.val) != -1;
		// boolean bGot = warrior.indexOf(WARRIOR.GOT.val) != -1;
		// boolean bPastDue = warrior.indexOf(WARRIOR.PAST_DUE.val) != -1;
		boolean bStatistics = warrior.indexOf(WARRIOR.STATISTICS.val) != -1;

		if (bJoin)
			this.joinWarrior(warrior);
		if (bGet && !bStatistics)
			this.getWarriorPrise(warrior);

		warrior = this.getWarriorData();

		boolean _bJoin = warrior.indexOf(WARRIOR.JOIN.val) != -1;
		boolean _bGet = warrior.indexOf(WARRIOR.GET.val) != -1;
		// boolean _bGot = warrior.indexOf(WARRIOR.GOT.val) != -1;
		// boolean _bPastDue = warrior.indexOf(WARRIOR.PAST_DUE.val) != -1;
		// boolean _bStatistics = warrior.indexOf(WARRIOR.STATISTICS.val) != -1;

		if (!_bJoin && !_bGet)
			this.isWarriorRun = true;

		if (bJoin && !_bJoin)
			ln(": Join Warrior Success");
		if (bGet && !_bGet)
			ln(": Get Warrior Reward Success");
	}

	public void runTrain() {
		if (this.player.getEp() > this.ConserveEP)
			return;

		if (!this.isMianChiRewardGet) {
			this.startTrain(3);
			ln(": start-train (3)");
			return;
		}

		long ts = T.TS() - T.TS_OF_HOUR_OF_TODAY(8);
		int h = -1;
		if (ts > 0)
			h = (int) (24 - ts / T._1HinMS);
		else
			h = (int) ((ts * -1 + T._1HinMS - 1) / T._1HinMS);
		this.startTrain(h);

		ln(": start-train (" + h + ")");
	}

	public void runWeal() {
		if (T.TS_OF_HOUR_OF_TODAY(8) > T.TS())
			if (this.canGetWeal(null) == DECISION.TRUE)
				this.startWeal();

		if (this.canGetWealAct(null) == DECISION.TRUE)
			this.actWeal();

		if (this.canGetWeal(null) == DECISION.FALSE
				&& this.canGetWealAct(null) == DECISION.FALSE)
			this.isWealRun = true;
	}

	public void runDailySignIn() {
		if (!isSignIn) {
			try {
				boolean b = this.DailySignIn();
				if (b)
					this.isSignIn = true;
			} catch (JSONException e) {
			}
		}
	}

	public void activeBeauty() {
		DECISION d1 = this.canSetBeauty(null, 1);
		DECISION d4 = this.canSetBeauty(null, 4);
		DECISION d7 = this.canSetBeauty(null, 7);
		DECISION d8 = this.canSetBeauty(null, 8);

		if (d1 == DECISION.TRUE)
			this.setBeautyEffect(1);
		if (d4 == DECISION.TRUE)
			this.setBeautyEffect(4);
		if (d7 == DECISION.TRUE && this.player.getDuelTimes() > 3)
			this.setBeautyEffect(7);
		if (d8 == DECISION.TRUE && this.player.getAcptTaskNum() > 5)
			this.setBeautyEffect(8);

		DECISION _d1 = this.canSetBeauty(null, 1);
		DECISION _d4 = this.canSetBeauty(null, 4);
		DECISION _d7 = this.canSetBeauty(null, 7);
		DECISION _d8 = this.canSetBeauty(null, 8);

		if (_d1 == DECISION.FALSE && _d4 == DECISION.FALSE
				&& _d7 == DECISION.FALSE && _d8 == DECISION.FALSE) {
			this.isBeautyRun = true;
			ln(": all beauty set");
		}

		if (d1 == DECISION.TRUE && _d1 == DECISION.FALSE)
			ln(": Beauty Gallery Set 1");
		if (d4 == DECISION.TRUE && _d4 == DECISION.FALSE)
			ln(": Beauty Gallery Set 4");
		if (d7 == DECISION.TRUE && _d7 == DECISION.FALSE)
			ln(": Beauty Gallery Set 7");
		if (d8 == DECISION.TRUE && _d8 == DECISION.FALSE)
			ln(": Beauty Gallery Set 8");
	}

	public boolean sellAllItems() throws Exception {
		KVPair[] ps = new KVPair[] { new KVPair("callback_func_name",
				"itemClass.dragItemCallback") };
		this.eng.post(this.bUrl
				+ "/modules/role_item.php?act=sell_all_temp&timeStamp="
				+ Calendar.getInstance().getTimeInMillis(), null, ps);
		String str = this.eng.getResponseHtml();

		System.out.println(str);

		JSONObject job = new JSONObject(str);

		if (job.has("removeItems"))
			return true;
		else
			return false;
	}

	public boolean sellItem(String id) throws Exception {
		String url = this.bUrl + "/modules/role_item.php?act=drag_item&id="
				+ id + "&from=pack&to=shop&shop_id=0&timeStamp="
				+ Calendar.getInstance().getTimeInMillis()
				+ "&callback_func_name=itemClass.dragItemCallback";

		this.eng.get(url, null, null);
		String str = this.eng.getResponseHtml();
		str = str + "";

		return false;
	}

	public boolean dragItem(String id, ITEM_POS from, ITEM_POS to)
			throws Exception {
		return this.dragItem(id, from, to, null);
	}

	public boolean dragItem(String id, ITEM_POS from, ITEM_POS to, Point pnt)
			throws Exception {
		String url = this.bUrl + "/modules/role_item.php?act=drag_item&id="
				+ id + "&from=" + from.val + "&to=" + to.val + "&timeStamp="
				+ Calendar.getInstance().getTimeInMillis()
				+ "&callback_func_name=itemClass.dragItemCallback";

		if (pnt != null)
			url += "&pos_x=" + pnt.x + "&pos_y=" + pnt.y;

		if (to == ITEM_POS.SHOP)
			url += "&shop_id=0";

		this.eng.get(url, null, null);
		String str = this.eng.getResponseHtml();

		JSONObject job = new JSONObject(str);

		if (job.has("fromId"))
			return true;
		else
			return false;

	}

	public void getGift(String[] infos) throws Exception {

		String str = exec(this.bUrl
				+ "/modules/awards.php?timeStamp="
				+ Calendar.getInstance().getTimeInMillis()
				+ "&callback_func_name=ajaxCallback&callback_obj_name=dlg_awards");

		Document doc = Jsoup.parse(str);
		Elements grid = doc.select("table.data_grid > tr");
		// System.out.println(grid.toString());

		Pattern p = Pattern.compile("awards_link_([0-9]+)");
		int lines = grid.size();
		for (int i = 0; i < lines; i++) {
			Element el = grid.get(i);
			String s = el.toString();

			if (s.indexOf("\u7ACB\u5373\u9886\u53D6") == -1)
				continue;

			boolean bfind = false;
			for (String info : infos) {
				if (s.indexOf(info) != -1) {
					bfind = true;
					break;
				}
			}

			if (!bfind)
				continue;

			Matcher m = p.matcher(s);
			if (m.find()) {
				// System.out.println(m.group(1));
				exec(this.bUrl + "/modules/awards.php?act=fetch&award_id="
						+ m.group(1) + "&timeStamp="
						+ Calendar.getInstance().getTimeInMillis()
						+ "&callback_func_name=awards_fetch_callback");
				// http://s8.hero.9wee.com/modules/awards.php?act=fetch&award_id=1686557&timeStamp=1341134253728&callback_func_name=awards_fetch_callback
			}
		}
	}

	private long ts() {
		return Calendar.getInstance().getTimeInMillis();
	}

	public String getRoleInfo2() throws Exception {
		String url = this.bUrl
				+ "/modules/role_info.php?timeStamp="
				+ ts()
				+ "&callback_func_name=callback_load_content&callback_obj_name=content";

		this.eng.get(url, null, null);
		return this.eng.getResponseHtml();
	}

	public void listPack() throws Exception {
		// BufferedWriter bw = new BufferedWriter(new FileWriter("c:\\a.txt"));
		// bw.write(getRoleInfo2());
		// bw.close();

		String str = getRoleInfo2();
		Pattern p = Pattern
				.compile("itemClass\\.roleItems[ ]*=[ ]*([{]\"equip\".*?[}]{3});");
		Matcher m = p.matcher(str);

		if (m.find()) {
			BufferedWriter bw = new BufferedWriter(new FileWriter("c:\\a.txt"));
			bw.write(m.group(1));
			bw.close();
		}
	}

	private void traverse(String str) throws JSONException {
		JSONObject jobj = new JSONObject(str);
		Iterator it = jobj.keys();
		while (it.hasNext()) {
			Object k = it.next();
			jobj.getJSONObject(k.toString());

		}
	}
}